CooperateISO - #1498
Conversation
drvinceknight
left a comment
There was a problem hiding this comment.
This looks really great, I enjoyed the preprint (congrats on the work)!
My requests are mainly stylistic as we tend to try and avoid inline comments (there are a number in the tests that I didn't comment on that could perhaps be moved to docstrings).
| @@ -1,4 +1,7 @@ | |||
| sphinx>=7.0.0,<9.0.0 | |||
There was a problem hiding this comment.
Can you help me understand why this change is needed? (This might be because of an upstream change.)
|
|
||
| # The theme to use for HTML and HTML Help pages. See the documentation for | ||
| # a list of builtin themes. | ||
| on_rtd = os.environ.get("READTHEDOCS", None) == "True" |
There was a problem hiding this comment.
Could you help me understand why this change? (It might be something got stale that I'm not remembering.)
| return opponent.history[-1] | ||
|
|
||
|
|
||
| # We describe memory-1 strategies as length-4 arrays, quantifying the probability of cooperation in the states [CC, CD, DC, DD]. |
There was a problem hiding this comment.
| # We describe memory-1 strategies as length-4 arrays, quantifying the probability of cooperation in the states [CC, CD, DC, DD]. |
| # Apply p_noise only to own strategy, not to opponent | ||
| # (the opponent strategy already includes noise effects). | ||
| own = my_strategy + p_noise * (1.0 - 2.0 * my_strategy) | ||
|
|
||
| # Flip CD/DC for opponent. | ||
| opp = opp_strategy[[0, 2, 1, 3]] | ||
|
|
||
| # Build the transition matrix. | ||
| trans_mat = np.array( | ||
| [ | ||
| own * opp, | ||
| own * (1.0 - opp), | ||
| (1.0 - own) * opp, | ||
| (1.0 - own) * (1.0 - opp), | ||
| ] | ||
| ).T | ||
|
|
||
| R, P, S, T = RPST | ||
| rewards = np.array([R, S, T, P], dtype=float) | ||
|
|
||
| # Don't include init state in summed rewards. | ||
| inv = np.linalg.inv(np.eye(4) - (1.0 - p_end) * trans_mat) | ||
|
|
||
| # Calculate expected reward, | ||
| reward = init_state @ (inv @ rewards - rewards) | ||
|
|
||
| # Avg. reward per step | ||
| return p_end * float(reward) / (1.0 - p_end) |
There was a problem hiding this comment.
Could you remove this inline comments and put the corresponding explanation in the docstring please.
| # Clamp to possible values, given noise | ||
| opp = np.clip(opponent, p_noise, 1.0 - p_noise) | ||
|
|
||
| # Setup initial state | ||
| init_state = np.zeros(4, dtype=np.float32) | ||
| init_state[init_state_idx] = 1.0 | ||
|
|
||
| # Define the objective function to minimize (negative reward) | ||
| def objective(params: np.ndarray) -> float: | ||
| return -get_reward(params, opp, init_state, p_end, p_noise, RPST) | ||
|
|
||
| x0 = np.array([0.5, 0.5, 0.5, 0.5]) | ||
| bounds = [(0.0, 1.0), (0.0, 1.0), (0.0, 1.0), (0.0, 1.0)] | ||
| result = minimize( | ||
| objective, x0, method="L-BFGS-B", bounds=bounds, options={"maxiter": 50} | ||
| ) | ||
|
|
||
| # result.fun is the minimum loss (-reward), result.x are the optimal parameters | ||
| return -result.fun, result.x |
There was a problem hiding this comment.
I think we can remove the inline comments here
| # Track the opponent's rate of cooperation (numerator, denominator) for each state. | ||
| # Assume we have seen the opponent play following TfT once in each state, | ||
| # to make the opponent-model well-defined from the start. | ||
| self.ewma_CC = [1.0, 1.0] | ||
| self.ewma_CD = [1.0, 1.0] | ||
| self.ewma_DC = [0.0, 1.0] | ||
| self.ewma_DD = [0.0, 1.0] | ||
|
|
||
| # Initial cooperation probabilities (num / den) | ||
| self.opp_model = [1.0, 0.0, 1.0, 0.0] | ||
| self.my_policy = [1.0, 0.0, 1.0, 0.0] |
There was a problem hiding this comment.
Can you move these inline comments to the docstring of the __init__
| # Estimate of the opponent's rate of playing D after C, taking noise | ||
| # into account. |
There was a problem hiding this comment.
| # Estimate of the opponent's rate of playing D after C, taking noise | |
| # into account. |
Adding 3 strategies (LongtermTfT, ISO, CooperateISO) from https://arxiv.org/abs/2303.03519.
Made a few changes relative to the versions used in the paper. Most importantly, ISO now uses
scipy.optimizeinstead of torch's Adam. This works equally well, is faster, and avoids having to import torch.Ran the CooperateISO implementation from this PR against all strategies in Axelrod-4.14.0, and verified that it outperforms EvolvedLookerUp2_2_2 and DBS at both noise levels 0% and 10%.
Fix Read the Docs build failures by updating documentation requirements and conf.py: